﻿using Irony.Interpreter;
using Irony.Interpreter.Ast;
using Irony.Parsing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Mi_Gramatica
{
    [Language("LPs", "1.2", "Lenguaje de pista by andy ")]
    class Gramatica : Grammar
    {
        public Gramatica()
            : base(caseSensitive: true) 
        { 
      StringLiteral cad = TerminalFactory.CreateCSharpString("cad");
      StringLiteral caracter = TerminalFactory.CreateCSharpChar("caracter");
      NumberLiteral num = TerminalFactory.CreateCSharpNumber("num");
      IdentifierTerminal id = TerminalFactory.CreateCSharpIdentifier("id");

      CommentTerminal SingleLineComment = new CommentTerminal("SingleLineComment", ">>","\n","\r\n");
      CommentTerminal DelimitedComment = new CommentTerminal("DelimitedComment", "<_", "_>");
      base.NonGrammarTerminals.Add(SingleLineComment);
      base.NonGrammarTerminals.Add(DelimitedComment);     
    
      KeyTerm Lbr = ToTerm("{");
      KeyTerm Rbr = ToTerm("}");
      KeyTerm Lpar = ToTerm("(");
      KeyTerm Rpar = ToTerm(")");

            CommentTerminal escape = new CommentTerminal("escape","\r\n");
           // RegexBasedTerminal cade = new RegexBasedTerminal("cade", "([0-9]*([a-z]|[A-Z])+[0-9]*)+");
         //   RegexBasedTerminal num = new RegexBasedTerminal("Number", "[0-9]+");
            base.NonGrammarTerminals.Add(escape);
       
            NonTerminal S = new NonTerminal("s"),
                        P = new NonTerminal("P"),
                        NPista = new NonTerminal("NPista"),
                        CPista = new NonTerminal("CPista"),
                        Tipo = new NonTerminal("Tipo"),
                        Decla_var = new NonTerminal("Decla_var"),
                        Decla_var_asig = new NonTerminal("Decla_var_asig"),
                        Decla_array = new NonTerminal("Decla_array"),
                        Decla_array_asig = new NonTerminal("Decla_array_asig"),
                        LE = new NonTerminal("LE"),
                        Dims = new NonTerminal("Dims"),
                        Asignacion = new NonTerminal("Asignacion"),
                        AsigSimplificada = new NonTerminal("AsigSimplificada"),
                        Spista = new NonTerminal("Spista"),
                        coment = new NonTerminal("coment"),
                        OPR = new NonTerminal("opr"),
                        Valor = new NonTerminal("Valor"),
                        e = new NonTerminal("E"),
                        Sent = new NonTerminal("Sent"),
                        If = new NonTerminal("if"),
                        LER = new NonTerminal("LER"),
                        Decla_metodos = new NonTerminal("Decla_metodos"),
                        Opr = new NonTerminal("Opr"),
                        E = new NonTerminal("E"),
                        LS = new NonTerminal("LS"),
                        doWhile_ = new NonTerminal("doWhile_"),
                        While_ = new NonTerminal("While_"),
                        For_ = new NonTerminal("For_"),
                        Fun = new NonTerminal("Fun"),
                        LDP = new NonTerminal("LDP"),
                        Switch_ = new NonTerminal("Switch_"),
                        For_Action = new NonTerminal("For_Action"),
                        Case_ = new NonTerminal("Case_"),
                        To = new NonTerminal("To"),
                        LCase = new NonTerminal("LCase"),
                        If_ = new NonTerminal("If_"),
                        LID=new NonTerminal("Lista_id");
            RegisterOperators(0,"=","+=","-=");
            RegisterOperators(1, Associativity.Left, "||", "&|", "!||");
            RegisterOperators(2, Associativity.Left, "&&", "!&&");
            RegisterOperators(3, Associativity.Right, "!");
            RegisterOperators(4, "==", "!=", ">", "<", ">=", "<=", "!¡");
            RegisterOperators(5, "+", "-");
            RegisterOperators(6, "%", "/", "*");
            RegisterOperators(7, "^");
            RegisterOperators(8, "++","--");
            RegisterBracePair("(", ")");
            RegisterBracePair("[", "]");
            MarkPunctuation( ",", "(", ")", "[", "]");
            MarkPunctuation(Eos);
S.Rule=P;
P.Rule = NPista + Indent + CPista + Dedent;

NPista.Rule = "Pista" + id + "extiende" + LID +Eos
        | "Pista" + id+Eos;

CPista.Rule = CPista +  Spista 
         |  Spista;

Tipo.Rule = ToTerm("entero")
        | "cadena"
        | "boolean"
        | "doble"
        | "caracter";
Spista.Rule = Decla_var +Eos
        | Decla_var_asig+Eos
        | Asignacion+Eos
        | Decla_metodos
        | Decla_array
        | Decla_array_asig;
Decla_metodos.Rule = ToTerm("Keep") + Tipo + id + Lpar + LDP + Rpar +Eos+ Indent + LS + Dedent
                    | ToTerm("Keep") + Tipo + id + Lpar + Rpar + Eos + Indent + LS + Dedent
                    | Tipo + id + Lpar + LDP + Rpar + Eos + Indent + LS + Dedent
                     | Tipo + id + Lpar + Rpar + Indent + LS + Dedent
                    | ToTerm("Principal") + Lpar + Rpar + Indent + LS + Dedent;

Decla_var.Rule = Decla_var + "," + id
          | ToTerm("Keep") + ToTerm("var") + Tipo + id
          | "var" + Tipo + id;

LID.Rule = LID + "," + id
    | id
    ;
Decla_var_asig.Rule = Decla_var + "=" + Valor;
          

Decla_array.Rule = Decla_var + Dims;

Decla_array_asig.Rule = Decla_array+"="+ LE;

LE.Rule = LE + "," + E
    | LE + "," + Lbr + LE + Rbr
    | Lbr + LE + Rbr
    | E;

Dims.Rule = Dims + ToTerm("[") + E+ToTerm("]")
        | ToTerm("[") + E + ToTerm("]");

Asignacion.Rule = id +ToTerm("=")+ Valor
| id +ToTerm( "+=") + Valor
| AsigSimplificada;

AsigSimplificada.Rule = id + "++"
| id + "--"
| "--" + id
| "++" + id;



Opr.Rule = ToTerm("==")
| "<"
| ">"
| ">="
| "<="
| "!="
| "!¡";

Valor.Rule = E + Opr + E
| Valor + "||" + Valor
| Valor + "!||" + Valor
| Valor + "&|" + Valor
| Valor + "&&" + Valor
| Valor + "!&&" + Valor
| "!" + Valor
| E;

E.Rule = E + "+" + E
    | E + "-" + E
    | E + "*" + E
    | E + "/" + E
    | E + "%" + E
    | E + "^" + E
    | num
    | cad
    | id
    | "falso"
    | "verdadero"
    | caracter
    | Fun
    | "(" + Valor + ")"
    | id + "[" + E + "]"

    | AsigSimplificada
    ;

Sent.Rule = doWhile_
| Asignacion+Eos
| ToTerm("retorna") + Valor+Eos
| If_
| Switch_
| For_
| While_
| Decla_var+Eos
| Decla_var_asig+Eos
| Decla_array_asig+Eos
| Decla_array+Eos
| "salir"+Eos;

NonGrammarTerminals.Add(ToTerm(@"\"));

If_.Rule = "si" + Lpar + Valor + Rpar + Eos+Indent + LS + Dedent
        | "si" + Lpar + Valor + Rpar +Eos+ Indent + LS + Dedent + "sino" +Eos+ Indent + LS + Dedent;

Case_.Rule = "case" + num +Eos + Indent + LS + Dedent;

LCase.Rule = LCase + Case_
| Case_;

Switch_.Rule = "switch" + Lpar + E + Rpar + Eos+Indent + LCase + "default" + Indent + LS + Dedent + Dedent
            | "switch" + Lpar + E + Rpar + Eos+Indent + LCase + Dedent;

For_Action.Rule = Asignacion;

For_.Rule = "para" + Lpar + Asignacion + ";" + Valor + ";" + For_Action + Rpar +Eos+ Indent + LS + Dedent;

While_.Rule = "mientras" + Lpar + Valor + Rpar +Eos+ Indent + LS + Dedent;

LS.Rule = LS +Sent
    |  Sent;

doWhile_.Rule = "hacer" + Indent + LS + Dedent + "mientras" + Lpar + Valor + Rpar;

LDP.Rule = LDP + "," + Tipo + id
     | Tipo + id;



Fun.Rule = "Reproducir" + Lpar + id + "," + E + "," + E + "," + E + Rpar
        | "Esperar" + Lpar + E + "," + E + Rpar
       // | "principal" + Lpar + Rpar + LS
        | "Ordenar" + Lpar + id + "," + To + Rpar
        | ToTerm("Sumarizar") + Lpar + E + Rpar
        | "Longitud" + Lpar + E + Rpar
        | "Mensaje" + Lpar + E + Rpar;

To.Rule = ToTerm("ascendente")
    | "descendente"
    | "impares"
    | "pares"
    | "primos";

this.Root = S;


        }

      public override void CreateTokenFilters(LanguageData language, TokenFilterList filters) {
      var outlineFilter = new CodeOutlineFilter(language.GrammarData, 
        OutlineOptions.ProduceIndents | OutlineOptions.CheckBraces, ToTerm(@"\")); // "\" is continuation symbol
      filters.Add(outlineFilter);
    }
        
    }
}
